package com.hk.pinda.zuul.filter;

import com.hk.pinda.auth.client.properties.AuthClientProperties;
import com.hk.pinda.auth.client.utils.JwtTokenClientUtils;
import com.hk.pinda.auth.utils.JwtUserInfo;
import com.hk.pinda.base.BaseResult;
import com.hk.pinda.context.BaseContextConstants;
import com.hk.pinda.exception.BizException;
import com.hk.pinda.utils.StrHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;



/**
 * 解析token中的用户信息 过滤器
 */
@Component
public class TokenContextFilter extends BaseFilter {
    @Autowired
    private AuthClientProperties authClientProperties;
    @Autowired
    private JwtTokenClientUtils jwtTokenClientUtils;

   /* @Override
    public String filterType() {
        // 前置过滤器
        return FilterConstants.PRE_TYPE;
    }*/

    /**
     * filterOrder：通过int值来定义过滤器的执行顺序，数字越大，优先级越低
     */
   /* @Override
    public int filterOrder() {
        *//*
         一定要在
         org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter
         过滤器之后执行，因为这个过滤器做了路由,而我们需要这个路由信息来鉴权
         这个过滤器会将我们鉴权需要的信息放置在请求上下文中
         *//*
        return FilterConstants.PRE_DECORATION_FILTER_ORDER + 1;
    }*/

    /**
     * 返回一个boolean类型来判断该过滤器是否要执行
     */
   /* @Override
    public boolean shouldFilter() {
        return true;
    }*/
    private void addHeader(ServerWebExchange.Builder requestBuilder, String name, Object value) {
        if (StringUtils.isEmpty(value)) {
            return;
        }
        // ctx.addZuulRequestHeader(name, StrHelper.encode(value.toString()));
        requestBuilder.request(builder -> builder.header(name, StrHelper.encode(value.toString())));
    }


    /**
     * 全局过滤器实现
     *
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // 获取 Request 和 Response 对象
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

        // 不进行拦截的地址
        if (isIgnoreToken(exchange)) {
            // 放行
            return chain.filter(exchange);
        }

        // 获取头文件中的令牌信息
        //获取token， 解析，然后将信息放入 header
        //1, 获取token
        String userToken = request.getHeaders().getFirst(authClientProperties.getUser().getHeaderName());

        //2, 解析token
        JwtUserInfo userInfo = null;

        try {
            userInfo = jwtTokenClientUtils.getUserInfo(userToken);
        } catch (BizException e) {
            errorResponse(response, e.getMessage(), e.getCode(), 200);
            return response.setComplete();
        } catch (Exception e) {
            errorResponse(response, "解析token出错", BaseResult.FAIL_CODE, 200);
            return response.setComplete();
        }

        //3, 将信息放入header
        if (userInfo != null) {
            ServerWebExchange.Builder mutate = exchange.mutate();
            addHeader(mutate, BaseContextConstants.JWT_KEY_NAME, userInfo.getName());
            addHeader(mutate, BaseContextConstants.JWT_KEY_ORG_ID, userInfo.getOrgId());
            addHeader(mutate, BaseContextConstants.JWT_KEY_USER_ID, userInfo.getUserId());
            addHeader(mutate, BaseContextConstants.JWT_KEY_STATION_ID, userInfo.getStationId());
            addHeader(mutate, BaseContextConstants.JWT_KEY_ACCOUNT, userInfo.getAccount());
            mutate.build();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 2;
    }
}